/*
 * CBufferStream.cpp
 *
 *  Created on: 07.03.2012
 *      Author: Caffeine
 */




#include "CBufferStream.h"
#include <cstring>

namespace irr{
namespace memory{

#define Cache_Size 16
//#define PVoid(data,position) (void*)(&((irr::c8*)data)[position])
#define PVoid(data,position) &((irr::c8*)data)[position]

void CBufferStream::checkSize(irr::u32 needSize){
	int add=getPosition()+needSize-allocated;
	if (add<=0){
		return;
	}
	uses+=needSize;
	irr::u8 block_count=ceil(needSize/Cache_Size);
	allocated=block_count*Cache_Size;
	void*newData=new irr::u8[allocated];
	if (data!=0){
		memcpy(PVoid(newData,0),PVoid(data,0),uses);
	}
	if (free_on_destroy && data!=0){
		delete[]data;
	}
	free_on_destroy=true;
	data=newData;
}

void*CBufferStream::getBuffer(){
	return PVoid(data,0);
}

irr::u32 CBufferStream::getSize(){
	return uses;
}
void CBufferStream::setPosition(irr::u32 p){
	position=p;
}

void CBufferStream::clear(){
	if (free_on_destroy && data!=0){
		delete[]data;
	}
	data=0;
	allocated=0;
	uses=0;
	position=0;
}

irr::u32 CBufferStream::getPosition(){
	return position;
}
void CBufferStream::write(void*buffer,irr::u32 size){
	if (buffer==0){
		if (free_on_destroy && data!=0){
			delete[]data;
		}
		data=new irr::u8[size];
		allocated=size;
		uses=size;
		position=0;
		free_on_destroy=true;
	}else{
		checkSize(size);
		memcpy(PVoid(data,getPosition()),buffer,size);
		position+=size;
	}
}

void CBufferStream::read(void*buffer,irr::u32 size){
	memcpy(buffer,PVoid(data,getPosition()),size);
	position+=size;
}

void CBufferStream::setMemoryData(void*begin,irr::u32 size,bool _free_on_destroy){
	if (free_on_destroy && data!=0){
		delete[]data;
	}
	data=begin;
	allocated=size;
	uses=size;
	free_on_destroy=_free_on_destroy;
	position=0;
	if (begin==0){
		begin=new irr::u8[size];
		free_on_destroy=true;
	}
}

CBufferStream::CBufferStream():allocated(0),uses(0),data(0),free_on_destroy(false),position(0){

}
CBufferStream::~CBufferStream(){
	clear();
}

}//namespace memory
}//namespace irr
